package club.baimahu.pencil.miaosha.controller;


import club.baimahu.pencil.annotation.Timer;
import club.baimahu.pencil.base.AjaxResult;
import club.baimahu.pencil.miaosha.domain.Stock;
import club.baimahu.pencil.miaosha.domain.User;
import club.baimahu.pencil.miaosha.service.StockService;
import club.baimahu.pencil.miaosha.service.UserService;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 抢购控制器
 *
 * @author zhanghongjiang
 * @version 1.0
 * @date 2021/9/13 16:26
 */
@Slf4j
@RequestMapping("/stock")
@Controller
public class StockController {

    @Autowired
    StockService stockService;

    @Autowired
    UserService userService;

    //可通过后台配置
    Date startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2021-09-13 23:58:00");

    RateLimiter rateLimiter = RateLimiter.create(20);

    public StockController() throws ParseException {
    }


    /**
     * 获得请求秒杀接口所需的哈希验证码，用于控制开始时间，防止恶意刷接口
     *
     * @param userId 为方便测试，实际应由服务器判断登录用户
     * @param sid
     * @return
     */
    @RequestMapping("/getVerifyHash")
    @ResponseBody
    public String getVerifyHash(Integer userId, Integer sid) {

        //未到秒杀时间
        if (new Date().before(startTime)) {
            return null;
        }

        if (userId == null || sid == null) {
            throw new IllegalArgumentException("userID , sid cannot be null");
        }

        return userService.getVerifyHash(userId, sid);

    }





    /**
     * @param sid        库存id
     * @param userId     为方便测试，实际应由服务器判断登录用户
     * @param verifyHash hash验证码
     * @return
     */
    @RequestMapping("/createOptimisticOrderWithHash")
    @ResponseBody
    @Timer
    public AjaxResult createOptimisticOrderWithHash(int sid, int userId, String verifyHash) {

        log.info("调用下单接口,userId={},sid={}",userId, sid);

        boolean banned = userService.checkUserIsBanned(userId);

        if (banned) {
            log.warn("用户请求频繁，已被拦截，userId = {}", userId);
            return AjaxResult.warning("request too much , denied ");
        }else{
            userService.increaseUserRequestTime(userId);
        }

        if (!userService.verify(userId, sid, verifyHash)) {
            log.warn("未通过hash校验");
            throw new RuntimeException("未通过hash校验");
        }

        if (!rateLimiter.tryAcquire(1000, TimeUnit.MILLISECONDS)) {
            log.warn("该请求被限流,userId={},verifyHash={}",userId,verifyHash);
            return AjaxResult.warning("limited");
        }

        log.info("开始下单,userId={},sid={}",userId, sid);

        stockService.createOrder(sid,userId);

        userService.deleteVerifyHash(userId, sid);

        return AjaxResult.success("OK");
    }


    /**
     * 查询库存
     * @param sid 库存id
     * @return
     */
    @RequestMapping("/stock/{sid}")
    @ResponseBody
    public Stock getStock(@PathVariable  int sid){
        Stock stock = stockService.getStock(sid);
        return stock;
    }


/*    // 增加用户
    @RequestMapping("/addUsers")
    @ResponseBody
    public String addUsers() {
        for (int i = 12; i < 10000; i++) {
            User user = new User();
            user.setId(i);
            user.setUsername("name_" + i);
            userService.addUser(user);
        }
        return "success";
    }*/
}
